﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Metro.Kashikoi.Common.Entity
{
    /// <summary>
    /// This interface provides the methods to persist the entities.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IRepository<T> where T : class
    {
        /// <summary>
        /// Gets the query.
        /// </summary>
        /// <returns>A collection that contains the elements from source that have type T.</returns>
        IQueryable<T> GetQuery();

        /// <summary>
        /// Filters a sequence of values based on a predicate.
        /// </summary>
        /// <param name="predicate">A function to test each element for a condition.</param>
        /// <returns>A list of entity from the input sequence that satisfy the condition.</returns>
        IEnumerable<T> Where(Func<T, bool> predicate);

        /// <summary>
        /// Filters a sequence of values based on a predicate.
        /// </summary>
        /// <typeparam name="TResult">The type to filter the elements of the sequence on.</typeparam>
        /// <param name="predicate">The predicate.</param>
        /// <returns>A collection that contains the elements from source that have type TResult.</returns>
        IEnumerable<TResult> Where<TResult>(Func<TResult, bool> predicate) where TResult : T;

        /// <summary>
        /// Returns the only entity of a sequence that satisfies a specified condition
        /// </summary>
        /// <param name="predicate">A function to test each entity for a condition.</param>
        /// <returns>The single entity of the input sequence that satisfies a condition.</returns>
        T Single(Func<T, bool> predicate);

        /// <summary>
        /// Counts the only entities based on a predicate.
        /// </summary>
        /// <param name="predicate">A function to test each element for a condition.</param>
        /// <returns>The count number of the entities.</returns>
        int Count(Func<T, bool> predicate);

        /// <summary>
        /// Deletes the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        void Delete(T entity);

        /// <summary>
        /// Adds the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        void Add(T entity);

        /// <summary>
        /// Attaches the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        void Attach(T entity);

        /// <summary>
        /// Removes the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        void Remove(T entity);
    }
}
